import time
import json
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import TimeoutException, WebDriverException
import undetected_chromedriver as uc
import random

import traceback
from pathlib import Path



from selenium.webdriver.chrome.service import Service


from urllib.parse import urlparse

class WeiboLogin:
    def __init__(self, headless=False):
        self.driver = None
        self.cookies = None
        self.headless = headless
        self.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0"
        self.init_driver()
        
    def init_driver(self):
        """初始化浏览器驱动"""
        chrome_options = Options()
        if self.headless:
            chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--disable-dev-shm-usage')
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
        chrome_options.add_experimental_option('useAutomationExtension', False)
        
        # 添加网络相关选项
        chrome_options.add_argument('--disable-web-security')
        chrome_options.add_argument('--allow-running-insecure-content')
        chrome_options.add_argument('--ignore-certificate-errors')
        chrome_options.add_argument('--disable-extensions')
        
        # 设置用户代理
        chrome_options.add_argument(f'--user-agent={self.user_agent}')
        
        # 添加额外的请求头
        chrome_options.add_argument('--accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
        chrome_options.add_argument('--accept-language=zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2')
        chrome_options.add_argument('--accept-encoding=gzip, deflate, br')
        
        try:
            driver_path="E:\\D\\phpStudy\\WWW\\linux_python\\linux_weibo_crawl\\chromedriver-ben\\chromedriver.exe"
            service = Service(driver_path)
            # 使用undetected_chromedriver避免被检测
            self.driver = webdriver.Chrome(service=service,options=chrome_options)
            
            # 执行JavaScript来设置更多请求头
            self.driver.execute_script("""
                Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
                window.navigator.chrome = {
                    runtime: {},
                };
            """)
            
            # 设置页面加载超时
            self.driver.set_page_load_timeout(30)
            self.driver.set_script_timeout(30)
            
        except Exception as e:
            print(f"初始化浏览器失败: {e}")
            raise
    
    def set_custom_headers(self):
        """设置自定义请求头"""
        # 在页面加载前执行JavaScript设置请求头
        script = """
        // 覆盖XMLHttpRequest的open和send方法
        (function() {
            var originalOpen = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function() {
                this.setRequestHeader('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
                this.setRequestHeader('Accept-Language', 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2');
                this.setRequestHeader('Accept-Encoding', 'gzip, deflate, br');
                this.setRequestHeader('Connection', 'keep-alive');
                this.setRequestHeader('Upgrade-Insecure-Requests', '1');
                return originalOpen.apply(this, arguments);
            };
        })();
        """
        self.driver.execute_script(script)
    
    def get_with_retry(self, url, max_retries=3):
        """带重试机制的页面访问"""
        for attempt in range(max_retries):
            try:
                print(f"尝试访问页面 (尝试 {attempt + 1}/{max_retries})...")
                self.driver.get(url)
                return True
            except TimeoutException:
                print(f"页面加载超时，尝试 {attempt + 1}/{max_retries}")
                if attempt < max_retries - 1:
                    wait_time = random.randint(5, 10)
                    print(f"等待 {wait_time} 秒后重试...")
                    time.sleep(wait_time)
                else:
                    print("已达到最大重试次数")
                    return False
            except Exception as e:
                print(f"访问页面失败: {e}")
                if attempt < max_retries - 1:
                    wait_time = random.randint(5, 10)
                    print(f"等待 {wait_time} 秒后重试...")
                    time.sleep(wait_time)
                else:
                    print("已达到最大重试次数")
                    return False
        return False
    
    def get_qr_code(self):
        """获取微博二维码登录页面"""
        print("正在打开微博登录页面...")
        
        # 设置自定义请求头
        self.set_custom_headers()
        
        # 尝试多个可能的URL
        urls = [
            "https://passport.weibo.com/sso/signin?entry=wapsso&source=wapsso&url=https://m.weibo.cn/",
            "https://weibo.com/login.php",
            "https://m.weibo.cn/login"
        ]
        
        for url in urls:
            if self.get_with_retry(url):
                print(f"成功访问: {url}")
                break
            else:
                print(f"访问 {url} 失败")
                if url == urls[-1]:
                    return None
        
        try:
            # 等待页面加载完成
            WebDriverWait(self.driver, 15).until(
                EC.presence_of_element_located((By.TAG_NAME, "body"))
            )
            
            
            # 等待二维码加载 - 使用多种可能的选择器
            qr_selectors = [
                (By.XPATH, "//img[contains(@class, 'w-full') and contains(@class, 'h-full')]"),
                (By.XPATH, "//img[contains(@src, 'qr.weibo.cn')]"),
                (By.XPATH, "//img[contains(@src, 'qrcode')]"),
                (By.CLASS_NAME, "qrcode-img"),
                (By.CLASS_NAME, "qrcode")
            ]
            
            qr_img = None
            for by, selector in qr_selectors:
                try:
                    qr_img = WebDriverWait(self.driver, 20).until(
                        EC.presence_of_element_located((by, selector))
                    )
                    break
                except:
                    continue
            
            if not qr_img:
                # 尝试截图当前页面以便调试
                self.driver.save_screenshot("qr_not_found.png")
                print("未找到二维码元素，页面已截图保存为 qr_not_found.png")
                return None
                
            print("二维码已加载")
            
            # 获取二维码图片
            qr_src = qr_img.get_attribute("src")
            print(f"二维码链接: {qr_src}")
            
            # 保存二维码图片供手动扫描
            if qr_src:
                try:
                    # 使用requests下载二维码图片
                    headers = {
                        'User-Agent': self.user_agent,
                        'Accept': 'image/webp,*/*',
                        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Connection': 'keep-alive',
                        'Referer': 'https://passport.weibo.com/'
                    }
                    
                    response = requests.get(qr_src, headers=headers, timeout=15)
                    with open("weibo_qr_code.png", "wb") as f:
                        f.write(response.content)
                    print("二维码已保存为 weibo_qr_code.png，可供手动扫描")
                except Exception as e:
                    print(f"保存二维码图片失败: {e}")
            
            return qr_src
        except Exception as e:
            print(f"获取二维码失败: {e}")
            # 尝试截图当前页面以便调试
            try:
                self.driver.save_screenshot("error_screenshot.png")
                print("当前页面已截图保存为 error_screenshot.png")
            except:
                pass
            return None
    
    def wait_for_login(self, timeout=180):
        """等待用户扫码登录"""
        print("请使用微博客户端扫描二维码登录...")
        start_time = time.time()
        last_url = self.driver.current_url
        
        while time.time() - start_time < timeout:
            try:
                # 检查当前URL是否变化
                current_url = self.driver.current_url
                if current_url != last_url:
                    print(f"检测到URL变化: {current_url}")
                    last_url = current_url
                
                # 检查是否登录成功
                if ("m.weibo.cn" in current_url or "weibo.com" in current_url) and \
                   ("passport" not in current_url and "sso" not in current_url and "login" not in current_url):
                    print("登录成功!")
                    # 获取cookies
                    self.cookies = {}
                    for cookie in self.driver.get_cookies():
                        self.cookies[cookie['name']] = cookie['value']
                    return True
                
                # 检查是否有错误提示
                error_selectors = [
                    "//*[contains(text(), '失败')]",
                    "//*[contains(text(), '错误')]",
                    "//*[contains(text(), '超时')]",
                    "//*[contains(text(), 'expired')]",
                    "//*[contains(text(), 'invalid')]",
                    "//*[contains(@class, 'error')]",
                    "//*[contains(@class, 'alert')]"
                ]
                
                for selector in error_selectors:
                    try:
                        error_elements = self.driver.find_elements(By.XPATH, selector)
                        for el in error_elements:
                            if el.is_displayed() and el.text.strip():
                                error_msg = el.text
                                print(f"检测到错误提示: {error_msg}")
                                return False
                    except:
                        continue
                    
            except Exception as e:
                print(f"检查登录状态时出错: {e}")
                
            time.sleep(3)
        
        print("登录超时")
        return False
    
    def get_cookies(self):
        """获取登录后的cookies"""
        return self.cookies
    
    def save_cookies(self, filename="weibo_cookies.json"):
        """保存cookies到文件"""
        if self.cookies:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(self.cookies, f, indent=4, ensure_ascii=False)
            print(f"Cookies已保存到 {filename}")
    
    def close(self):
        """关闭浏览器"""
        if self.driver:
            try:
                self.driver.quit()
                print("浏览器已关闭")
            except:
                pass

def main():
    # 创建登录实例
    weibo_login = WeiboLogin(headless=False)
    
    try:
        # 获取二维码
        qr_src = weibo_login.get_qr_code()
        if not qr_src:
            print("无法获取二维码，程序退出")
            return
        
        # 显示二维码链接，方便用户手动扫码
        print(f"请使用微博客户端扫描二维码或访问: {qr_src}")
        
        # 等待用户扫码登录
        if weibo_login.wait_for_login():
            # 获取cookies
            cookies = weibo_login.get_cookies()
            print("获取到的Cookies:")
            for name, value in cookies.items():
                print(f"{name}: {value}")
            
            # 保存cookies到文件
            weibo_login.save_cookies()
            
            # 使用cookies访问微博
            session = requests.Session()
            session.headers.update({
                'User-Agent': weibo_login.user_agent,
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                'Accept-Encoding': 'gzip, deflate, br',
                'Connection': 'keep-alive',
                'Upgrade-Insecure-Requests': '1'
            })
            
            for name, value in cookies.items():
                session.cookies.set(name, value)
            
            # 测试访问微博首页
            try:
                response = session.get("https://m.weibo.cn", timeout=15)

                #time.sleep(2000000)
                if response.status_code == 200:
                    print("成功使用cookies访问微博")
                    if "转发" in response.text or "评论" in response.text:
                        print("确认已登录微博")
                    else:
                        print("可能未成功登录")
                else:
                    print(f"访问微博失败，状态码: {response.status_code}")
                time.sleep(2000000)
            except Exception as e:
                print(f"测试访问微博时出错: {e}")
        else:
            print("登录失败")
    
    except Exception as e:
        print(f"程序执行出错: {e}")
        # 尝试截图
        try:
            weibo_login.driver.save_screenshot("final_error_screenshot.png")
            print("错误页面已截图保存为 final_error_screenshot.png")
        except:
            pass
    
    # finally:
    #     #关闭浏览器
    #     weibo_login.close()

if __name__ == "__main__":
    main()
